// Office文件处理工具，用于处理docx和xlsx文件，支持表格、图片、文本替换等功能。
package utils

import (
	"database/sql"
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"time"

	"bsm/logger"
	"bsm/models"

	"github.com/xuri/excelize/v2"
)

// ExcelTag 解析Excel相关的标签
type ExcelTag struct {
	Sheet string
	Pos   string
}

type XlsxTools struct {
	File         *excelize.File
	ProjectState int
}

func (xt *XlsxTools) NewXlsxTools(xlsxfile string, dtype int) error {

	file, err := excelize.OpenFile(xlsxfile)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "NewXlsxTools",
			"error":     err.Error(),
		}).Error("打开XLSX文件失败")
		return err
	}
	xt.File = file
	xt.ProjectState = dtype
	return nil
}

func (xt *XlsxTools) GetSheetNames() []string {
	return xt.File.GetSheetList()
}
func (xt *XlsxTools) GetSheetNameByIndex(index int) string {
	return xt.File.GetSheetName(index)
}

// FillDataToExcel 增强版Excel数据填充
func (xt *XlsxTools) FillDataToExcel(config models.ExcelFillConfig) error {
	// 验证参数
	if err := xt.validateConfig(config); err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "FillDataToExcel",
			"error":     err.Error(),
		}).Error("验证配置参数失败")
		return err
	}

	// 填充表头（如果需要）
	if config.WithHeader {
		if err := xt.fillHeaders(config); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "FillDataToExcel",
				"error":     err.Error(),
			}).Error("填充表头失败")
			return err
		}
	}

	// 插入足够的数据行
	templateRow := config.StartRow // 假设模板行为数据开始行
	startRow := templateRow + 1
	dataCount := len(config.Data)
	// 1. 复制追加模板行的格式（不含公式）
	rowCount := dataCount - 1
	if dataCount <= config.RowsPerPage {
		rowCount = config.RowsPerPage - 1
	}
	for i := range rowCount {
		targetRow := startRow + i
		if err := xt.File.DuplicateRowTo(config.SheetName, templateRow, targetRow); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "FillDataToExcel",
				"error":     err.Error(),
			}).Error("复制追加模板行失败")
			return err
		}
		//log.Printf("%s第%d行复制成功", config.SheetName, targetRow)
	}

	// 2.填充数据
	dataStartRow := config.StartRow
	if config.WithHeader && config.HeaderRow < config.StartRow {
		dataStartRow = config.HeaderRow + 1
	}

	for i, rowData := range config.Data {
		currentRow := dataStartRow + i
		xt.File.SetCellValue(config.SheetName, "A"+strconv.Itoa(currentRow), i+1)
		if err := xt.fillRow(config.SheetName, currentRow, config.ColumnMap, rowData); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "FillDataToExcel",
				"error":     err.Error(),
			}).Errorf("第%d行填充数据失败: %v", i+1, err)
			return fmt.Errorf("第%d行: %w", i+1, err)
		}
		//log.Printf("%s第%d行填充数据成功", config.SheetName, currentRow)
	}

	// 4. 调整公式引用（如果需要）
	// if err := xt.adjustFormulasAfterInsert(config.SheetName, dataStartRow, rowsToInsert); err != nil {
	// 	return err
	// }

	// 自动调整列宽（如果需要）
	if config.AutoSize {
		if err := xt.autoSizeColumns(config); err != nil {
			return err
		}
	}

	return nil
}

// validateConfig 验证配置参数
func (xt *XlsxTools) validateConfig(config models.ExcelFillConfig) error {
	if xt.File == nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "validateConfig",
		}).Error("Excel文件未初始化")
		return fmt.Errorf("Excel文件未初始化")
	}
	if config.SheetName == "" {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "validateConfig",
		}).Error("工作表名不能为空")
		return fmt.Errorf("工作表名不能为空")
	}
	if config.StartRow < 1 {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "validateConfig",
		}).Error("起始行必须大于0")
		return fmt.Errorf("起始行必须大于0")
	}
	if len(config.Data) == 0 {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "validateConfig",
		}).Error("没有数据需要填充")
		return fmt.Errorf("没有数据需要填充")
	}
	if len(config.ColumnMap) == 0 {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "validateConfig",
		}).Error("列映射关系不能为空")
		return fmt.Errorf("列映射关系不能为空")
	}

	// 检查工作表是否存在
	sheets := xt.File.GetSheetList()
	found := false
	for _, sheet := range sheets {
		if sheet == config.SheetName {
			found = true
			break
		}
	}
	if !found {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "validateConfig",
		}).Errorf("工作表 '%s' 不存在", config.SheetName)
		return fmt.Errorf("工作表 '%s' 不存在", config.SheetName)
	}

	return nil
}

// fillHeaders 填充表头
func (xt *XlsxTools) fillHeaders(config models.ExcelFillConfig) error {
	headerRow := config.HeaderRow
	if headerRow == 0 {
		headerRow = config.StartRow - 1
		if headerRow < 1 {
			headerRow = 1
		}
	}

	for dataField, excelCol := range config.ColumnMap {
		headerName := dataField // 默认使用数据字段名
		if customName, exists := config.HeaderNames[dataField]; exists {
			headerName = customName
		}

		cell := fmt.Sprintf("%s%d", excelCol, headerRow)
		if err := xt.File.SetCellValue(config.SheetName, cell, headerName); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "fillHeaders",
				"error":     err.Error(),
			}).Errorf("设置表头 %s 失败: %v", cell, err)
			return fmt.Errorf("设置表头 %s 失败: %w", cell, err)
		}

		// 可选：设置表头样式
		if err := xt.applyHeaderStyle(config.SheetName, cell); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "fillHeaders",
				"error":     err.Error(),
			}).Errorf("设置表头样式 %s 失败: %v", cell, err)
		}
	}

	return nil
}

// fillRow 填充单行数据
func (xt *XlsxTools) fillRow(sheet string, row int, columnMap map[string]string, rowData map[string]interface{}) error {
	for dataField, excelCol := range columnMap {
		if value, exists := rowData[dataField]; exists {
			cell := fmt.Sprintf("%s%d", excelCol, row)
			if strings.Contains(fmt.Sprintf("%v", value), "{row}") {
				value = strings.ReplaceAll(fmt.Sprintf("%v", value), "{row}", strconv.Itoa(row))
				xt.File.SetCellFormula(sheet, cell, fmt.Sprintf("%v", value))
			} else {
				if err := xt.File.SetCellValue(sheet, cell, value); err != nil {
					logger.WithFields(map[string]interface{}{
						"layer":     "utils",
						"operation": "fillRow",
						"error":     err.Error(),
					}).Errorf("单元格 %s 填充数据失败: %v", cell, err)
					return fmt.Errorf("单元格 %s: %w", cell, err)
				}
			}
		}
	}
	return nil
}

// RebuildFooterFormulas 重新构建表尾公式
func (xt *XlsxTools) RebuildFooterFormulas(sheet string, dataStartRow, footerRow int, dataCount int, summaryColumns []string) error {
	dataEndRow := dataStartRow + dataCount - 1

	for _, colName := range summaryColumns {
		footerCell := fmt.Sprintf("%s%d", colName, footerRow)

		// 构建新的求和公式
		sumFormula := fmt.Sprintf("=SUM(%s%d:%s%d)", colName, dataStartRow, colName, dataEndRow)
		logger.Infof("设置%s合计公式 %s: %s", sheet, footerCell, sumFormula)
		if err := xt.File.SetCellFormula(sheet, footerCell, sumFormula); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "RebuildFooterFormulas",
				"error":     err.Error(),
			}).Errorf("设置合计公式失败 %s: %v", footerCell, err)
			return fmt.Errorf("设置合计公式失败 %s: %w", footerCell, err)
		}
	}

	return nil
}

func (xt *XlsxTools) RebuildFooterFormulasWithPage(sheet string, dataStartRow, footerRow, pageSize, totalRows int, summaryColumns []string) error {
	if totalRows <= 0 {
		return nil
	}

	// 计算总页数
	totalPages := (totalRows + pageSize - 1) / pageSize

	for page := 0; page < totalPages; page++ {
		// 计算当前页的数据范围
		pageStartRow := dataStartRow + page*pageSize
		pageEndRow := pageStartRow + pageSize - 1
		if pageEndRow > dataStartRow+totalRows-1 {
			pageEndRow = dataStartRow + totalRows - 1
		}

		// 当前页的footer行
		currentFooterRow := footerRow + page*(pageSize+1) // 假设每页之间有间隔

		for _, colName := range summaryColumns {
			footerCell := fmt.Sprintf("%s%d", colName, currentFooterRow)

			// 构建当前页的求和公式
			sumFormula := fmt.Sprintf("=SUM(%s%d:%s%d)", colName, pageStartRow, colName, pageEndRow)

			if err := xt.File.SetCellFormula(sheet, footerCell, sumFormula); err != nil {
				logger.WithFields(map[string]interface{}{
					"layer":     "utils",
					"operation": "RebuildFooterFormulas",
					"page":      page + 1,
					"cell":      footerCell,
					"error":     err.Error(),
				}).Errorf("设置分页合计公式失败")
				return fmt.Errorf("设置分页合计公式失败 %s: %w", footerCell, err)
			}

			logger.WithFields(map[string]interface{}{
				"layer":   "utils",
				"page":    page + 1,
				"cell":    footerCell,
				"formula": sumFormula,
			}).Debugf("设置分页合计公式")
		}
	}

	return nil
}

// RebuildSubtotalFormulas 重新构建小计公式（支持多页）
func (xt *XlsxTools) RebuildSubtotalFormulas(sheet string, pageStarts []int, footerRows []int, summaryColumns []string) error {
	for i, pageStart := range pageStarts {
		if i >= len(footerRows) {
			break
		}

		pageEnd := pageStart + 45 // 假设每页45行数据
		if i < len(pageStarts)-1 {
			pageEnd = pageStarts[i+1] - 1
		}

		for _, colName := range summaryColumns {
			footerCell := fmt.Sprintf("%s%d", colName, footerRows[i])
			subtotalFormula := fmt.Sprintf("=SUBTOTAL(9, %s%d:%s%d)", colName, pageStart, colName, pageEnd)

			if err := xt.File.SetCellFormula(sheet, footerCell, subtotalFormula); err != nil {
				logger.WithFields(map[string]interface{}{
					"layer":     "utils",
					"operation": "RebuildSubtotalFormulas",
					"error":     err.Error(),
				}).Errorf("设置小计公式失败 %s: %v", footerCell, err)
				return fmt.Errorf("设置小计公式失败 %s: %w", footerCell, err)
			}
		}
	}

	return nil
}

// autoSizeColumns 自动调整列宽
func (xt *XlsxTools) autoSizeColumns(config models.ExcelFillConfig) error {
	// 收集所有需要调整的列
	columns := make(map[string]bool)
	for _, col := range config.ColumnMap {
		columns[col] = true
	}

	// 为每列设置合适的宽度
	for col := range columns {
		if err := xt.File.SetColWidth(config.SheetName, col, col, 15); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "autoSizeColumns",
				"error":     err.Error(),
			}).Errorf("调整列 %s 宽度失败: %v", col, err)
			return fmt.Errorf("调整列 %s 宽度失败: %w", col, err)
		}
	}

	return nil
}

// applyHeaderStyle 应用表头样式（可选）
func (xt *XlsxTools) applyHeaderStyle(sheet, cell string) error {
	// 创建或获取表头样式
	style, err := xt.File.NewStyle(&excelize.Style{
		Font: &excelize.Font{
			Bold: true,
			Size: 12,
		},
		Alignment: &excelize.Alignment{
			Horizontal: "center",
			Vertical:   "center",
		},
		Fill: excelize.Fill{
			Type:    "pattern",
			Color:   []string{"#DDEBF7"},
			Pattern: 1,
		},
	})
	if err != nil {
		return err
	}

	return xt.File.SetCellStyle(sheet, cell, cell, style)
}

// ConvertStructToMap 将结构体切片转换为map切片
func (xt *XlsxTools) ConvertStructToMap(data interface{}, tagName string) ([]map[string]interface{}, error) {
	// 这里可以使用之前讨论的反射方法
	// 简化实现：假设已经是map切片
	if mapData, ok := data.([]map[string]interface{}); ok {
		return mapData, nil
	}

	return nil, fmt.Errorf("不支持的数据类型")
}

// SaveFile 保存文件
func (xt *XlsxTools) SaveFile(filename string) error {
	if xt.File == nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "SaveFile",
			"error":     "Excel文件未初始化",
		}).Errorf("Excel文件未初始化")
		return fmt.Errorf("Excel文件未初始化")
	}
	return xt.File.SaveAs(filename)
}

// 在保存文件前强制重新计算所有公式
func (xt *XlsxTools) SaveFileWithRecalc(filename string) error {
	if xt.File == nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "SaveFileWithRecalc",
			"error":     "Excel文件未初始化",
		}).Errorf("Excel文件未初始化")
		return fmt.Errorf("Excel文件未初始化")
	}

	// 设置工作簿强制重新计算
	calcID := uint(191029)
	concurrentCalc := false
	CalcOnSave := true
	FullCalcOnLoad := true
	calcOpts := &excelize.CalcPropsOptions{
		CalcID:         &calcID,
		ConcurrentCalc: &concurrentCalc,
		CalcOnSave:     &CalcOnSave,
		FullCalcOnLoad: &FullCalcOnLoad,
	}
	err := xt.File.SetCalcProps(calcOpts)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "SaveFileWithRecalc",
			"error":     err.Error(),
		}).Errorf("设置计算属性失败: %v", err)
		return fmt.Errorf("设置计算属性失败: %w", err)
	}

	return xt.File.SaveAs(filename)
}

// Close 关闭文件
func (xt *XlsxTools) Close() error {
	if xt.File != nil {
		return xt.File.Close()
	}
	return nil
}

// RemoveExternalLinks 删除Excel文件中的外部链接
func (xt *XlsxTools) RemoveExternalLinks() error {
	f := xt.File
	defer f.Close()

	// 获取所有工作表
	sheets := f.GetSheetList()

	for _, sheet := range sheets {
		// 检查并删除外部链接
		if err := removeSheetExternalLinks(f, sheet); err != nil {
			logger.WithFields(map[string]interface{}{
				"layer":     "utils",
				"operation": "RemoveExternalLinks",
				"error":     err.Error(),
			}).Warnf("工作表 %s 处理失败: %v", sheet, err)
		}
	}

	// 保存清理后的文件
	if err := f.Save(); err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "RemoveExternalLinks",
			"error":     err.Error(),
		}).Errorf("保存文件失败: %v", err)
		return fmt.Errorf("保存文件失败: %w", err)
	}

	return nil
}

// removeSheetExternalLinks 删除Excel工作表中的外部链接
func removeSheetExternalLinks(f *excelize.File, sheet string) error {
	// 获取工作表的单元格
	rows, err := f.GetRows(sheet)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "utils",
			"operation": "removeSheetExternalLinks",
			"error":     err.Error(),
		}).Errorf("获取工作表 %s 单元格失败: %v", sheet, err)
		return err
	}

	externalLinkIndicators := []string{
		"[", // 外部工作簿引用，如 [Budget.xlsx]
		"!",
		".xlsx]",
		".xls]",
		".xlsm]",
		"http://",
		"https://",
		"ftp://",
		"=HYPERLINK(",
	}

	for rowIdx, row := range rows {
		for colIdx, cellValue := range row {
			for _, indicator := range externalLinkIndicators {
				if strings.Contains(cellValue, indicator) {
					// 清空包含外部链接的单元格
					colName, _ := excelize.ColumnNumberToName(colIdx + 1)
					cellRef := fmt.Sprintf("%s%d", colName, rowIdx+1)

					// 先获取公式，如果是公式且包含外部链接，则清空
					if formula, _ := f.GetCellFormula(sheet, cellRef); formula != "" {
						f.SetCellFormula(sheet, cellRef, "") // 清空公式
					}
					f.SetCellValue(sheet, cellRef, "") // 清空值
				}
			}
		}
	}

	return nil
}

// 辅助函数处理指针类型
// func getValue[T any](ptr *T) interface{} {
// 	if ptr == nil {
// 		return "<nil>"
// 	}
// 	return *ptr
// }

// 解析Excel标签
func parseExcelTag(tag reflect.StructTag) *ExcelTag {
	sheetTag := tag.Get("sheet")
	posTag := tag.Get("pos")

	if sheetTag == "" || posTag == "" {
		return nil
	}

	return &ExcelTag{
		Sheet: sheetTag,
		Pos:   posTag,
	}
}

// 获取结构体字段到Excel位置的映射
func getExcelFieldMapping(model interface{}) map[string]ExcelTag {
	mapping := make(map[string]ExcelTag)

	t := reflect.TypeOf(model)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		excelTag := parseExcelTag(field.Tag)

		if excelTag != nil {
			mapping[field.Name] = *excelTag
		}
	}

	return mapping
}

// 设置字段值（支持多类型）
func setFieldValueFromString(field reflect.Value, value string) error {
	if value == "" {
		field.Set(reflect.Zero(field.Type()))
		return nil
	}

	switch field.Kind() {
	case reflect.String:
		field.SetString(value)

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if val, err := strconv.ParseInt(value, 10, 64); err == nil {
			field.SetInt(val)
		} else {
			//return fmt.Errorf("无法将 '%s' 转换为整数: %v", value, err)
			logger.Warnf("无法将 '%s' 转换为整数,简单返回0: %v", value, err)
			field.SetInt(0)
		}

	case reflect.Float32, reflect.Float64:
		if val, err := strconv.ParseFloat(value, 64); err == nil {
			field.SetFloat(val)
		} else {
			// return fmt.Errorf("无法将 '%s' 转换为浮点数: %v", value, err)
			logger.Warnf("无法将 '%s' 转换为浮点数,简单返回0: %v", value, err)
			field.SetFloat(0)
		}

	case reflect.Bool:
		if val, err := strconv.ParseBool(value); err == nil {
			field.SetBool(val)
		} else {
			switch strings.ToLower(value) {
			case "是", "真", "true", "1":
				field.SetBool(true)
			case "否", "假", "false", "0", "":
				field.SetBool(false)
			default:
				return fmt.Errorf("无法将 '%s' 转换为布尔值", value)
			}
		}

	default:
		return setCustomFieldValue(field, value)
	}

	return nil
}

// 设置自定义类型字段值
func setCustomFieldValue(field reflect.Value, value string) error {
	fieldType := field.Type()

	// 处理 sql.NullString
	if fieldType == reflect.TypeOf(sql.NullString{}) {
		if value == "" {
			field.Set(reflect.ValueOf(sql.NullString{Valid: false}))
		} else {
			field.Set(reflect.ValueOf(sql.NullString{
				String: value,
				Valid:  true,
			}))
		}
		return nil
	}

	// 处理 sql.NullInt64
	if fieldType == reflect.TypeOf(sql.NullInt64{}) {
		if value == "" {
			field.Set(reflect.ValueOf(sql.NullInt64{Valid: false}))
		} else {
			if val, err := strconv.ParseInt(value, 10, 64); err == nil {
				field.Set(reflect.ValueOf(sql.NullInt64{
					Int64: val,
					Valid: true,
				}))
			} else {
				return fmt.Errorf("无法将 '%s' 转换为整数", value)
			}
		}
		return nil
	}

	// 处理 sql.NullFloat64
	if fieldType == reflect.TypeOf(sql.NullFloat64{}) {
		if value == "" {
			field.Set(reflect.ValueOf(sql.NullFloat64{Valid: false}))
		} else {
			if val, err := strconv.ParseFloat(value, 64); err == nil {
				field.Set(reflect.ValueOf(sql.NullFloat64{
					Float64: val,
					Valid:   true,
				}))
			} else {
				return fmt.Errorf("无法将 '%s' 转换为浮点数", value)
			}
		}
		return nil
	}

	// 处理 sql.NullTime
	if fieldType == reflect.TypeOf(sql.NullTime{}) {
		if value == "" {
			field.Set(reflect.ValueOf(sql.NullTime{Valid: false}))
		} else {
			fixedDate := FixDateString(value)
			parsedTime, err := time.Parse("2006-01-02", fixedDate)
			if err != nil {
				field.Set(reflect.ValueOf(sql.NullTime{Valid: false}))
			} else {
				field.Set(reflect.ValueOf(sql.NullTime{
					Time:  parsedTime,
					Valid: true,
				}))
			}
		}
		return nil
	}

	return fmt.Errorf("不支持的字段类型: %v", fieldType)
}

// ReadSingleRecord 直接通过字段名映射读取
func (xt *XlsxTools) ReadSingleRecord(model interface{}) error {
	excelMapping := getExcelFieldMapping(model)

	value := reflect.ValueOf(model)
	if value.Kind() != reflect.Ptr || value.IsNil() {
		return fmt.Errorf("model必须是非空指针")
	}
	value = value.Elem()

	for fieldName, excelTag := range excelMapping {
		field := value.FieldByName(fieldName)
		if !field.IsValid() || !field.CanSet() {
			continue
		}

		cellValue, err := xt.File.GetCellValue(excelTag.Sheet, excelTag.Pos)
		if err != nil {
			return fmt.Errorf("读取单元格 %s!%s 失败: %v", excelTag.Sheet, excelTag.Pos, err)
		}

		if err := setFieldValueFromString(field, cellValue); err != nil {
			return fmt.Errorf("设置字段 %s 值失败: %v", fieldName, err)
		}
	}

	return nil
}

// 获取嵌套结构体的Excel映射（支持无限层级嵌套）
func getExcelMappingRecursive(model interface{}) map[string]ExcelTag {
	mapping := make(map[string]ExcelTag)

	var traverse func(reflect.Type, string)
	traverse = func(typ reflect.Type, prefix string) {
		// 处理指针类型
		if typ.Kind() == reflect.Ptr {
			typ = typ.Elem()
		}

		// 只处理结构体类型
		if typ.Kind() != reflect.Struct {
			return
		}

		for i := 0; i < typ.NumField(); i++ {
			field := typ.Field(i)
			fieldName := field.Name

			// 构建完整字段路径
			fullFieldName := fieldName
			if prefix != "" {
				fullFieldName = prefix + "." + fieldName
			}

			// 如果是嵌套结构体（匿名嵌入或命名嵌套）
			if field.Anonymous || (field.Type.Kind() == reflect.Struct && field.Type != reflect.TypeOf(time.Time{})) {
				// 递归处理嵌套结构体
				traverse(field.Type, fullFieldName)
				continue
			}

			// 解析Excel标签
			excelTag := parseExcelTag(field.Tag)
			if excelTag != nil {
				mapping[fullFieldName] = *excelTag
			}
		}
	}

	t := reflect.TypeOf(model)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	traverse(t, "")

	return mapping
}

// 支持嵌套结构体的读取器
func (xt *XlsxTools) ReadSingleRecordNested(model interface{}) error {
	excelMapping := getExcelMappingRecursive(model)

	value := reflect.ValueOf(model)
	if value.Kind() != reflect.Ptr || value.IsNil() {
		return fmt.Errorf("model必须是非空指针")
	}
	value = value.Elem()

	for fieldPath, excelTag := range excelMapping {
		// 根据字段路径获取嵌套字段
		field, err := getNestedField(value, fieldPath)
		if err != nil {
			return fmt.Errorf("获取字段 %s 失败: %v", fieldPath, err)
		}

		if !field.IsValid() || !field.CanSet() {
			continue
		}

		// 读取Excel单元格数据
		cellValue, err := xt.File.GetCellValue(excelTag.Sheet, excelTag.Pos)
		if err != nil {
			return fmt.Errorf("读取单元格 %s!%s 失败: %v", excelTag.Sheet, excelTag.Pos, err)
		}

		// 设置字段值
		if err := setFieldValueFromString(field, cellValue); err != nil {
			return fmt.Errorf("设置字段 %s 值失败: %v", fieldPath, err)
		}
	}

	return nil
}

// 根据字段路径获取嵌套字段的值
func getNestedField(parent reflect.Value, fieldPath string) (reflect.Value, error) {
	parts := strings.Split(fieldPath, ".")
	current := parent

	for _, part := range parts {
		if current.Kind() == reflect.Ptr {
			if current.IsNil() {
				// 如果指针为nil，需要初始化
				newValue := reflect.New(current.Type().Elem())
				current.Set(newValue)
				current = newValue.Elem()
			} else {
				current = current.Elem()
			}
		}

		if current.Kind() != reflect.Struct {
			return reflect.Value{}, fmt.Errorf("路径 %s 不是结构体", part)
		}

		field := current.FieldByName(part)
		if !field.IsValid() {
			return reflect.Value{}, fmt.Errorf("字段 %s 不存在", part)
		}

		current = field
	}

	return current, nil
}

// 统一的读取接口，自动检测是否包含嵌套结构体
func (xt *XlsxTools) ReadRecord(model interface{}) error {
	// 检查是否包含嵌套结构体
	if hasNestedStruct(model) {
		return xt.ReadSingleRecordNested(model)
	} else {
		return xt.ReadSingleRecord(model)
	}
}

// 检查是否包含嵌套结构体
func hasNestedStruct(model interface{}) bool {
	t := reflect.TypeOf(model)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	if t.Kind() != reflect.Struct {
		return false
	}

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		if field.Anonymous || (field.Type.Kind() == reflect.Struct && field.Type != reflect.TypeOf(time.Time{})) {
			return true
		}
	}

	return false
}

// 读取二维表格数据
func (xt *XlsxTools) ReadTableRecords(model interface{}, startRow, endRow int) ([]interface{}, error) {
	// 获取列映射
	columnMapping := getColumnMapping(model)
	if len(columnMapping) == 0 {
		return nil, fmt.Errorf("没有找到列映射配置")
	}

	var records []interface{}
	t := reflect.TypeOf(model).Elem()

	// 遍历指定行范围
	for row := startRow; row <= endRow; row++ {
		record := reflect.New(t).Interface()

		// 填充单行数据
		if err := xt.fillRecordFromRow(record, row, columnMapping); err != nil {
			return nil, fmt.Errorf("第 %d 行数据读取失败: %v", row, err)
		}

		records = append(records, record)
	}

	return records, nil
}

// 获取列映射
func getColumnMapping(model interface{}) map[string]string {
	mapping := make(map[string]string)

	t := reflect.TypeOf(model)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		sheet := field.Tag.Get("sheet")
		column := field.Tag.Get("col")

		if sheet != "" && column != "" {
			mapping[field.Name] = column
		}
	}

	return mapping
}

// 从单行填充记录
func (xt *XlsxTools) fillRecordFromRow(record interface{}, row int, columnMapping map[string]string) error {
	value := reflect.ValueOf(record).Elem()

	for fieldName, column := range columnMapping {
		// 构建单元格位置，如 "B2", "C2"
		cell := fmt.Sprintf("%s%d", column, row)

		// 获取sheet名称（从第一个字段获取）
		sheet := getSheetName(record)

		// 读取单元格值
		cellValue, err := xt.File.GetCellValue(sheet, cell)
		if err != nil {
			return err
		}

		// 设置字段值
		field := value.FieldByName(fieldName)
		if field.IsValid() && field.CanSet() {
			if err := setFieldValueFromString(field, cellValue); err != nil {
				return fmt.Errorf("字段 %s 解析失败: %v", fieldName, err)
			}
		}
	}

	return nil
}

// 获取sheet名称
func getSheetName(model interface{}) string {
	t := reflect.TypeOf(model).Elem()
	if t.NumField() > 0 {
		return t.Field(0).Tag.Get("sheet")
	}
	return ""
}

// 自动检测数据行范围（从startRow开始直到空行）
func (xt *XlsxTools) ReadTableRecordsAuto(model interface{}, startRow int) ([]interface{}, error) {
	columnMapping := getColumnMapping(model)
	sheet := getSheetName(model)

	var records []interface{}
	t := reflect.TypeOf(model).Elem()

	row := startRow
	for {
		// 检查第一列是否为空（作为行结束标志）
		firstValue, _ := xt.File.GetCellValue(sheet, "A"+strconv.Itoa(row))

		if strings.TrimSpace(firstValue) == "" {
			break // 遇到空行，停止读取
		}

		record := reflect.New(t).Interface()
		if err := xt.fillRecordFromRow(record, row, columnMapping); err != nil {
			return nil, err
		}

		records = append(records, record)
		row++
	}

	return records, nil
}

// 写入单个记录到Excel
func (xt *XlsxTools) WriteSingleRecord(model interface{}) error {
	excelMapping := getExcelFieldMapping(model)
	value := reflect.ValueOf(model)

	if value.Kind() == reflect.Ptr {
		value = value.Elem()
	}

	for fieldName, excelTag := range excelMapping {
		field := value.FieldByName(fieldName)
		if !field.IsValid() {
			continue
		}
		var cellValue interface{}

		switch v := field.Interface().(type) {
		case sql.NullTime:
			if v.Valid {
				cellValue = v.Time.Format("2006-01-02")
			} else {
				cellValue = ""
			}
		case sql.NullString:
			if v.Valid {
				cellValue = v.String
			} else {
				cellValue = ""
			}
		case sql.NullInt64:
			if v.Valid {
				cellValue = v.Int64
			} else {
				cellValue = 0
			}
		case sql.NullFloat64:
			if v.Valid {
				cellValue = v.Float64
			} else {
				cellValue = 0.0
			}
		default:
			cellValue = field.Interface()
		}

		if err := xt.File.SetCellValue(excelTag.Sheet, excelTag.Pos, cellValue); err != nil {
			return fmt.Errorf("写入单元格 %s!%s 失败: %v", excelTag.Sheet, excelTag.Pos, err)
		}
	}

	return nil
}
